#!/usr/bin/python

import localstore
import scanlocalfs

import json
import logging
import shutil
import os
import sys
import tempfile
import unittest2

def MakeFile(fname):
    d = os.path.dirname(fname)
    if not os.path.isdir(d):
        os.makedirs(d)
    fh = open(fname, 'wb')
    fh.write(os.path.basename(fname))
    fh.close


class TestLocalStore(unittest2.TestCase):
    def setUp(self):
        self.storepath = tempfile.mkdtemp()
        self.tmppaths = []
        self.store = localstore.LocalStore(self.storepath)
        self.maxDiff = None

    def GetTempPath(self):
        d = tempfile.mkdtemp()
        self.tmppaths.append(d)
        return d

    def CheckFile(self, fname):
        fh = open(fname, 'rb')
        self.assertEquals(os.path.basename(fname), fh.read())
        fh.close

    def test_Empty(self):
        v = scanlocalfs.SyncDirectory(self.store, self.GetTempPath(), '')
        self.assertEqual({'dirs': ['/'], 'files': {}},
                         json.loads(self.store.GetMetadata(v)))

        v = scanlocalfs.SyncDirectory(self.store, self.GetTempPath() + '/', '/')
        self.assertEqual({'dirs': ['/'], 'files': {}},
                         json.loads(self.store.GetMetadata(v)))

        restore = self.GetTempPath()
        scanlocalfs.RestoreSnapshot(self.store, '', restore, v)
        scanlocalfs.RestoreSnapshot(self.store, '/', restore, v)

    def test_Basic(self):
        t = self.GetTempPath()
        MakeFile(t + '/file-in-root')
        MakeFile(t + '/subdirectory/file-in-subdirectory')
        os.makedirs(t + '/empty-directory')
        os.symlink('/foo-target', t + '/symlink')

        v = scanlocalfs.SyncDirectory(self.store, t, '')
        self.assertEqual(
            {'dirs': ['/', '/empty-directory/', '/subdirectory/'],
             'files': {'/file-in-root': {'chunks': [['9de734cc478666c2383509681975ddd4',
                                                     12]],
                                         'size_bytes': 12},
                       '/subdirectory/file-in-subdirectory': {'chunks': [['3beaa4c88d65b4fcc1c5897443769cf1',
                                                                          20]],
                                                              'size_bytes': 20},
                       '/symlink': {'link': '/foo-target'}}},
            json.loads(self.store.GetMetadata(v)))

        restore = self.GetTempPath()
        scanlocalfs.RestoreSnapshot(self.store, '', restore, v)
        
        self.CheckFile(restore + '/file-in-root')
        self.CheckFile(restore + '/subdirectory/file-in-subdirectory')
        self.assertTrue(os.path.isdir(restore + '/empty-directory'))
        self.assertEqual(os.readlink(restore + '/symlink'), '/foo-target')

        partial_restore = self.GetTempPath()
        scanlocalfs.RestoreSnapshot(self.store, '/subdirectory', partial_restore, v)
        self.CheckFile(partial_restore + '/file-in-subdirectory')

        overwrite_folder = self.GetTempPath()
        MakeFile(overwrite_folder + '/partial')
        v = scanlocalfs.SyncDirectory(self.store, overwrite_folder, '/subdirectory')
        self.assertEqual(
            {'dirs': ['/', '/empty-directory/', '/subdirectory/'],
             'files': {'/file-in-root': {'chunks': [['9de734cc478666c2383509681975ddd4',
                                                     12]],
                                         'size_bytes': 12},
                       '/subdirectory/partial': {'chunks': [['0e87c1212a698494dcdb198af3e0eb2f',
                                                             7]],
                                                 'size_bytes': 7},
                       '/symlink': {'link': '/foo-target'}}},
            json.loads(self.store.GetMetadata(v)))

        restore = self.GetTempPath()
        scanlocalfs.RestoreSnapshot(self.store, '', restore, v)
        self.CheckFile(restore + '/file-in-root')
        self.CheckFile(restore + '/subdirectory/partial')
        self.assertTrue(os.path.isdir(restore + '/empty-directory'))
        self.assertEqual(os.readlink(restore + '/symlink'), '/foo-target')

    def test_CreatesAllUpstreamDirectories(self):
        t = self.GetTempPath()
        MakeFile(t + '/file-in-root')
        v = scanlocalfs.SyncDirectory(self.store, t, '/a/b/c/d/e/f/g/')
        self.assertEqual(
            {'dirs': ['/', '/a/', '/a/b/', '/a/b/c/', '/a/b/c/d/', '/a/b/c/d/e/', '/a/b/c/d/e/f/', '/a/b/c/d/e/f/g/'],
             'files': {'/a/b/c/d/e/f/g/file-in-root': {'chunks': [['9de734cc478666c2383509681975ddd4', 12]], 'size_bytes': 12}}},
            json.loads(self.store.GetMetadata(v)))
        restore = self.GetTempPath()
        scanlocalfs.RestoreSnapshot(self.store, '/a/b', restore, v)
        self.CheckFile(restore + '/c/d/e/f/g/file-in-root')
        
    def tearDown(self):
        shutil.rmtree(self.storepath)
        for d in self.tmppaths:
            shutil.rmtree(d)

if __name__ == '__main__':
    logging.basicConfig( stream=sys.stderr )
    logging.getLogger().setLevel('DEBUG')
    unittest2.main()
